package com.example.dicomviewer;

import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.daimajia.numberprogressbar.NumberProgressBar;
import com.example.dicomviewer.core.Config;
import com.hzc.widget.picker.file.FilePicker;
import com.hzc.widget.picker.file.FilePickerUiParams;

import org.json.JSONArray;
import org.json.JSONObject;
import org.xutils.common.Callback;
import org.xutils.http.RequestParams;
import org.xutils.x;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * 主界面(启动界面)
 * 显示两个按钮: 打开文件和打开文件夹
 * 主要是界面绘制和权限申请
 */
public class DicomViewer extends Activity implements View.OnClickListener {
    public static final int CHOOSE_PHOTO = 2;
    public static final int OPEN_ALBUM_PERMISSION_REQUEST_CODE = 3;
    private static final int FILE_SELECTER_REQUEST_CODE = 1;
    private static final int FILE_SELECTER_PERMISSION_REQUEST_CODE = 4;
    private static final int DOWNLOAD_REQUEST_CODE = 5;
    private static final String TAG = "DicomViewer";
    private static final int DOWNLOAD_RETURN_CODE = 6;
    private static int taskNum = 0;
    BroadcastReceiver broadcastReceiver;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        initDirs();
        initView();
        initEvent();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(broadcastReceiver);
    }

    private void initDirs() {
        FileUtil.createDir(this, Environment.DIRECTORY_DOWNLOADS);
        FileUtil.createDir(this, Environment.DIRECTORY_DOCUMENTS);
    }

    private void initView() {
        Button chooseFromAlbum = (Button) findViewById(R.id.choose_from_album);
        chooseFromAlbum.setOnClickListener(this);

        Button choose_file_folder = (Button) findViewById(R.id.choose_file_folder);
        choose_file_folder.setOnClickListener(this);

        Button download = (Button) findViewById(R.id.download);
        download.setOnClickListener(this);

        NumberProgressBar numberProgressBar = (NumberProgressBar) findViewById(R.id.number_progress_bar);
        numberProgressBar.setVisibility(View.INVISIBLE);
    }


    private void openAlbum() {
        Intent intent = new Intent("android.intent.action.GET_CONTENT");
        intent.setType("*/*");
        startActivityForResult(intent, CHOOSE_PHOTO);
    }

    // 调用下载的活动
    private void download() {
        // 写网络下载时，一定要检查
        // 1.权限申请
        // 2.网络安全策略和http
        // 3.请求的url与请求方法是否匹配
        // 4. logcat中的监视器一定要设置当前的程序  com.example.diconviewer
        Intent intent = new Intent(DicomViewer.this, DownloadActivity.class);
        startActivityForResult(intent, DOWNLOAD_RETURN_CODE);
    }

    // 解析出
    private ArrayList<String> parseJSON(String jsonData) {
        Log.d(TAG, jsonData);
        ArrayList<String> list = new ArrayList<String>();
        try {
            JSONObject jsonObject = new JSONObject(jsonData);
            JSONArray jsonArray = jsonObject.getJSONArray("data");
            for (int i = 0; i < jsonArray.length(); i++) {
                list.add(jsonArray.getString(i));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    private void downloadFileNames(String dirName) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 构建GET方法的请求
                    String url = Config.getBaseUrl() + "/findFiles/" + dirName;
                    Log.d(TAG, "<downloadFileNames> url: " + url);
                    Request request = new Request.Builder()
                            .url(url)
                            .build();
                    // 发起请求
                    OkHttpClient client = new OkHttpClient();
                    Response response = client.newCall(request).execute();
                    String responseData = response.body().string();
                    Log.d(TAG, "<downloadFileNames> recive response data: " + responseData);
                    ArrayList<String> fileNames = parseJSON(responseData);
                    downloadFiles(dirName, fileNames.toArray(new String[0]));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private void downloadFiles(String dirName, String[] fileNames) {
        long startTime = System.currentTimeMillis() / 1000;
        Log.d(TAG, "下载开始 , in " + startTime + "s");
        File dir = new File(getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS) + "/" + dirName);
        if (dir.exists()) {
            dir.delete();
        }
        ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(fileNames.length);
        taskNum = fileNames.length;
        NumberProgressBar numberProgressBar = (NumberProgressBar) findViewById(R.id.number_progress_bar);
        numberProgressBar.setMax(taskNum);
        DicomViewer.this.runOnUiThread(new Runnable() {
            public void run() {
                numberProgressBar.setVisibility(View.VISIBLE);
            }
        });
        queue.addAll(Arrays.asList(fileNames));
        // 100张图片
        // 8线程  最快8秒下完 有时15秒下完 但是也偶尔会21秒，感觉是够用了
        // 16线程 17或者19秒下完
        // 32线程 需要35秒左右
        int threadSize = 8;
        ExecutorService es = Executors.newFixedThreadPool(threadSize);
        AtomicInteger count = new AtomicInteger(0);
        for (int i = 0; i < threadSize; ++i) {
            es.execute(new Runnable() {
                @Override
                public void run() {
                    while (!queue.isEmpty()) {
                        try {
                            String fileName = queue.poll(30, TimeUnit.MINUTES);
                            String downloadUrl = Config.getBaseUrl() + "/download/" + dirName + "/" + fileName;
                            String savePath = getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS) + "/" + dirName + "/" + fileName;
                            File file = new File(savePath);
                            if (file.exists()) {
                                file.delete();
                            }
                            RequestParams params = new RequestParams(downloadUrl);
                            //自定义保存路径，Environment.getExternalStorageDirectory()：SD卡的根目录
                            params.setSaveFilePath(savePath);
                            params.setCancelFast(true);
                            //自动为文件命名
                            params.setAutoRename(true);
                            x.http().get(params, new Callback.CommonCallback<File>() {
                                @Override
                                public void onSuccess(File result) {
                                    Log.d(TAG, "<get> download success! result: " + result + " .After " + (System.currentTimeMillis() / 1000 - startTime) + " s");
                                    count.incrementAndGet();
                                    synchronized (count) {
                                        numberProgressBar.setProgress(count.get());
                                        if (count.get() == taskNum) {
                                            Toast.makeText(DicomViewer.this, "下载完成", Toast.LENGTH_SHORT).show();
                                            DicomViewer.this.runOnUiThread(new Runnable() {
                                                public void run() {
                                                    numberProgressBar.setVisibility(View.INVISIBLE);
                                                }
                                            });
                                        }
                                    }
                                }

                                @Override
                                public void onError(Throwable ex, boolean isOnCallback) {
                                    Toast.makeText(x.app(), ex.getMessage(), Toast.LENGTH_LONG).show();
                                    Log.d(TAG, "<get> download error ");
                                }

                                @Override
                                public void onCancelled(CancelledException cex) {
                                    Toast.makeText(x.app(), "cancelled", Toast.LENGTH_LONG).show();
                                    Log.d(TAG, "<get> download cancelled");
                                }

                                @Override
                                public void onFinished() {

                                }
                            });
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
        }
    }

    private void openDirChooser() {
        FilePicker.build(DicomViewer.this, 1)
                //设置初始打开的目录，默认为sdcard
                .setOpenFile(new File(getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).toString()))
                //设置选择文件还是文件夹，默认为文件
                .setPickFileType(FilePickerUiParams.PickType.FOLDER)
                //设置为单选，setMultiPick为设置多选，不可设置多选文件夹
                .setSinglePick(new FilePicker.OnSinglePickListener() {
                    @Override
                    public void pick(@NonNull File path) {
//                        tvResult.setText("单选 : \n" + path.getAbsolutePath());
                        Log.d("MainActivity", "get DIR path : " + path.getAbsolutePath());
                        SortedDicomDirReader sortedDicomDirReader = new SortedDicomDirReader();
                        ArrayList<String> arrayList = sortedDicomDirReader.Read(path.getAbsolutePath());
                        displayImage(arrayList);
                    }

                    @Override
                    public void cancel() {
                        Log.d("MainActivity", "cancle the select");
                        Toast.makeText(DicomViewer.this, "取消选择", Toast.LENGTH_SHORT).show();
                    }
                })
                //打开选择界面
                .open();
    }

    private void initEvent() {
        x.Ext.init(getApplication());
        x.Ext.setDebug(BuildConfig.DEBUG);// 是否输出debug日志, 开启debug会影响性能.
        x.view().inject(this);//没有用到view注解可以先不用
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.choose_from_album:
                if (ContextCompat.checkSelfPermission(DicomViewer.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(DicomViewer.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, OPEN_ALBUM_PERMISSION_REQUEST_CODE);
                } else {
                    openAlbum();
                }
                break;
            case R.id.choose_file_folder:
                if (ContextCompat.checkSelfPermission(DicomViewer.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(DicomViewer.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, FILE_SELECTER_PERMISSION_REQUEST_CODE);
                } else {
                    openDirChooser();
                }
                break;
            case R.id.download:
                if (ContextCompat.checkSelfPermission(DicomViewer.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(DicomViewer.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.INTERNET}, DOWNLOAD_REQUEST_CODE);
                } else {
                    download();
                }
                break;
            default:
                break;
        }
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
// 书上没有call super
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case CHOOSE_PHOTO:
                if (resultCode == RESULT_OK) {
                    handleImagaeOnKitKat(data);
                }
                break;
            case FILE_SELECTER_REQUEST_CODE:
                FilePicker.onActivityResult(this, requestCode, resultCode, data);
                break;
            case DOWNLOAD_RETURN_CODE:
                if (resultCode == RESULT_OK) {
                    String choosedDir = data.getStringExtra("name");
                    Log.d(TAG, "Download return msg: " + choosedDir);
                    downloadFileNames(choosedDir);
                }
                break;
            default:
                break;
        }
    }

    @TargetApi(19)
    private void handleImagaeOnKitKat(Intent data) {
        Uri uri = data.getData();
        String fileContent = "file:" + FileInfoUtils.getPath(this, uri);
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add(fileContent);
        displayImage(arrayList);
    }


    private String getImagePath(Uri uri, String selection) {
        String path = null;
        Cursor cursor = getContentResolver().query(uri, null, selection, null, null);
        if (cursor != null) {
            if (cursor.moveToFirst()) {
                path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
            }
            cursor.close();
        }
        return path;
    }

    private void displayImage(ArrayList<String> imagePaths) {
        if (imagePaths != null) {
            Log.d("MainActivity", "imagePath is " + imagePaths.toString());
            Intent intent = new Intent(DicomViewer.this, ViewerActivity.class);
            intent.putExtra("dir_array", imagePaths);
            startActivity(intent);
        } else {
            Toast.makeText(this, "failed to get image", Toast.LENGTH_SHORT).show();
        }
    }

    // 无论成功与否,发出申请(requestPermission)后这个函数都会回调
    // 第一个参数是请求码,与申请时的相同,第二个是当时请求的权限数组 , 第三个是申请的结果数组,也就是用于和PackageManager.PERMISSION_GRANTED比较
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case OPEN_ALBUM_PERMISSION_REQUEST_CODE:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // 刚才的权限申请成功,可以读取了
                    openAlbum();
                } else {
                    Toast.makeText(this, "You deied the permission", Toast.LENGTH_SHORT).show();
                }
                break;
            case FILE_SELECTER_PERMISSION_REQUEST_CODE:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    openDirChooser();
                } else {
                    Toast.makeText(this, "You deied the permission", Toast.LENGTH_SHORT).show();
                }
                break;
            case DOWNLOAD_REQUEST_CODE:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    download();
                } else {
                    Toast.makeText(this, "You deied the permission", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
        }
    }
}
